﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
#if NO_SILVERLIGHT
using System;
using System.Runtime.Serialization;
using System.ComponentModel;
using System.Reflection;
using BrainTechLLC.ThreadSafeObjects;
#if USE_HYPER
using Hyper.ComponentModel;
#endif

namespace BrainTechLLC
{
    public static class TypeAndPropExt
    {
        public static TypeAndProperties FindTypeAndProperties(this Type t)
        {
            return TypeAndProperties._typeAndPropertyMap[t];
        }

        public static void CacheTypeAndProperties(this TypeAndProperties tp)
        {
            TypeAndProperties._typeAndPropertyMap.AddOrSet(tp.ClassType, tp);
        }

        public static TypeAndProperties GetTypeAndProperties(this Type t)
        {
            TypeAndProperties props = TypeAndProperties._typeAndPropertyMap[t];
            if (props == null)
            {
                props = new TypeAndProperties(t);
                TypeAndProperties._typeAndPropertyMap.AddOrSet(t, props);
            }
            return props;
        }

        public static PropInfo GetPropInfo(this Type t, string propertyName)
        {
            TypeAndProperties props = TypeAndProperties._typeAndPropertyMap[t];
            if (props == null)
            {
                props = new TypeAndProperties(t);
                TypeAndProperties._typeAndPropertyMap.AddOrSet(t, props);
            }
            return props.Lookup[propertyName];
        }
    }

#if NO_SILVERLIGHT
    [TypeDescriptionProvider(typeof(HyperTypeDescriptionProvider))]
#endif
    [Serializable]
    public class TypeAndProperties
    {
        internal static readonly ThreadSafeLookup<Type, TypeAndProperties> _typeAndPropertyMap = new ThreadSafeLookup<Type, TypeAndProperties>();

        public TypeAndProperties(Type t)
        {
            ClassType = t;
            Lookup = new ThreadSafeLookup<string, PropInfo>();
            PropertyDescriptorCollection collection = TypeDescriptor.GetProperties(t);

            foreach (PropertyDescriptor prop in collection)
            {
                PropertyInfo propInfo = t.GetProperty(prop.Name);
                PropInfo info = new PropInfo(propInfo, prop);
                Lookup.Add(prop.Name, info);
            }
        }

        public void ForEachProperty(Action<PropInfo> action)
        {
            var allProps = Lookup.AllItems;

            for (int n = 0; n < allProps.Count; n++)
            {
                action(allProps[n]);
            }
        }

        public Type ClassType { get; set; }
        public ThreadSafeLookup<string, PropInfo> Lookup { get; set; }
    }
}

#endif